package com.seezoon.infrastructure.utils;

import java.util.regex.Pattern;

/**
 * BCD编码工具类
 * BCD (Binary-Coded Decimal) 是一种用二进制编码表示十进制数字的编码方式
 * 每个十进制数字用4位二进制数表示，例如：0=0000, 1=0001, ..., 9=1001
 */
public class BcdUtils {

    // 预编译的正则表达式
    private static final Pattern DIGIT_PATTERN = Pattern.compile("\\d+");

    /**
     * 将字符串转换为BCD编码的字节数组
     *
     * @param str 要转换的字符串，只能包含数字字符
     * @return BCD编码的字节数组
     * @throws IllegalArgumentException 如果字符串包含非数字字符
     */
    public static byte[] stringToBcd(String str) {
        if (str == null || str.isEmpty()) {
            return new byte[0];
        }

        // 验证字符串是否只包含数字
        if (!DIGIT_PATTERN.matcher(str).matches()) {
            throw new IllegalArgumentException("only allowed digit character: " + str);
        }

        // 如果字符串长度为奇数，在前面补0
        if (str.length() % 2 != 0) {
            str = "0" + str;
        }

        byte[] bcd = new byte[str.length() / 2];
        for (int i = 0; i < bcd.length; i++) {
            int high = Character.digit(str.charAt(i * 2), 10);
            int low = Character.digit(str.charAt(i * 2 + 1), 10);
            bcd[i] = (byte) ((high << 4) | low);
        }

        return bcd;
    }

    /**
     * 将BCD编码的字节数组转换为字符串
     *
     * @param bcd BCD编码的字节数组
     * @return 转换后的字符串
     */
    public static String bcdToString(byte[] bcd) {
        if (bcd == null || bcd.length == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (byte b : bcd) {
            int high = (b >> 4) & 0x0F;
            int low = b & 0x0F;

            // 验证BCD值的有效性
            if (high > 9 || low > 9) {
                throw new IllegalArgumentException("bcd code illegal " + Integer.toHexString(b & 0xFF));
            }
            sb.append(high);
            sb.append(low);
        }

        return sb.toString();
    }

    /**
     * 将BCD编码的字节数组转换为字符串，去除前导零
     *
     * @param bcd BCD编码的字节数组
     * @return 转换后的字符串，去除前导零
     */
    public static String bcdToStringTrimLeadingZero(byte[] bcd) {
        String result = bcdToString(bcd);
        // 去除前导零，但保留至少一个零
        String s = result.replaceFirst("^0+", "");
        return s.isEmpty() ? "0" : s;
    }
} 